package yxy.apple.protobuf.utility.generator;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import yxy.apple.util.FileUtility;
import yxy.apple.util.JSONUtility;

public abstract class ConstantsGenerator {
	private boolean trusted = false;

	public ConstantsGenerator(boolean trusted) {
		this.trusted = trusted;
	}

	public boolean trusted() {
		return this.trusted;
	}

	public void generate(JSONObject json, File output, String encoding) throws IOException {
		FileUtility.create(output);
		String content = this.assemble(json);
		FileOutputStream fos = new FileOutputStream(output);
		fos.write(content.getBytes(encoding));
		fos.flush();
		fos.close();
	}

	protected String assemble(JSONObject json) {
		JSONArray constants = JSONUtility.getArray(json, "Constants", null);
		return this.assembleContainer(0, null, null, null, constants);
	}

	protected String assembleContainer(int level, String type, String name, String comment, JSONArray fields) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(this.assembleHeader(level, type, name, comment));
		buffer.append(this.assembleFields(level + 1, type, fields));
		buffer.append(this.assembleFooter(level, type, name, comment));
		return buffer.toString();
	}

	protected String assembleFields(int level, String parent, JSONArray fields) {
		StringBuffer buffer = new StringBuffer();
		if (fields != null) {
			int size = fields.size();
			for (int i = 0; i < size; i++) {
				JSONObject field = JSONUtility.getJSONObject(fields, i, null);
				boolean visible = this.trusted || JSONUtility.getBoolean(field, "Public", false);
				Object value = JSONUtility.getObject(field, "Value", null);
				if (visible && value != null) {
					String type = JSONUtility.getString(field, "Type", "");
					String comment = JSONUtility.getString(field, "Comment", null);
					String name = JSONUtility.getString(field, "Name", null);
					if (value instanceof JSONArray) {
						JSONArray array = (JSONArray) value;
						buffer.append(this.assembleContainer(level, type, name, comment, array));
					} else {
						String string = (String) value;
						buffer.append(this.assembleField(level, parent, type, name, comment, string));
					}
				}
			}
		}
		return buffer.toString();
	}

	protected String indent(int level) {
		StringBuffer buffer = new StringBuffer("");
		for (int i = 0; i < level; i++) {
			buffer.append("\t");
		}
		return buffer.toString();
	}

	protected abstract String assembleHeader(int level, String type, String name, String comment);

	protected abstract String assembleFooter(int level, String type, String name, String comment);

	protected abstract String assembleField(int level, String parent, String type, String name, String comment, String value);

}
